import cv2
import time
import threading
from queue import Queue
from utils import faceUtils
import config
import numpy as np
import os

# 尝试导入PIL，如果失败则使用英文显示
try:
    from PIL import Image, ImageDraw, ImageFont
    PIL_AVAILABLE = True
except ImportError:
    PIL_AVAILABLE = False
    print("PIL not available, using English text only")


def put_chinese_text(img, text, position, font_size=32, color=(255, 255, 255)):
    """
    在图像上绘制中文文字
    """
    if not PIL_AVAILABLE:
        # 如果PIL不可用，直接使用OpenCV显示英文
        cv2.putText(img, text, position, cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
        return img
    
    try:
        # 转换图像格式
        img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(img_pil)
        
        # 尝试加载中文字体
        font_paths = [
            "C:/Windows/Fonts/simhei.ttf",  # Windows 黑体
            "C:/Windows/Fonts/msyh.ttc",    # Windows 微软雅黑
            "C:/Windows/Fonts/simsun.ttc",  # Windows 宋体
            "/System/Library/Fonts/PingFang.ttc",  # macOS
            "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",  # Linux
        ]
        
        font = None
        for font_path in font_paths:
            if os.path.exists(font_path):
                try:
                    font = ImageFont.truetype(font_path, font_size)
                    break
                except:
                    continue
        
        # 如果没有找到中文字体，使用默认字体
        if font is None:
            font = ImageFont.load_default()
        
        # 绘制文字
        draw.text(position, text, font=font, fill=color)
        
        # 转换回OpenCV格式
        return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
    except Exception as e:
        print(f"Error drawing Chinese text: {e}")
        # 出错时使用OpenCV显示英文
        cv2.putText(img, text, position, cv2.FONT_HERSHEY_SIMPLEX, 0.8, color, 2)
        return img


class FaceDetectionThread(threading.Thread):
    def __init__(self, frame_queue, result_queue):
        super().__init__()
        self.frame_queue = frame_queue
        self.result_queue = result_queue
        self.running = True
        
    def run(self):
        while self.running:
            try:
                if not self.frame_queue.empty():
                    frame_data = self.frame_queue.get(timeout=0.1)
                    frame, timestamp = frame_data
                    
                    # 缩小图像以提高处理速度
                    scale = config.PERFORMANCE_CONFIG['face_detection_scale']
                    small_frame = cv2.resize(frame, (0, 0), fx=scale, fy=scale)
                    small_frame_rgb = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB)
                    
                    # 获取人脸位置和编码
                    face_locations = faceUtils.get_face_locations(small_frame_rgb)
                    
                    if face_locations:
                        face_encodings = faceUtils.get_face_encodings_from_locations(small_frame_rgb, face_locations)
                        
                        if face_encodings:
                            best_match, best_distance = faceUtils.compare_faces(face_encodings[0])
                            threshold = config.PERFORMANCE_CONFIG['confidence_threshold']
                            if best_match and best_distance < threshold:
                                result = (best_match, best_distance, face_locations)
                            else:
                                result = ("Unknown", None, face_locations)
                        else:
                            result = (None, None, face_locations)
                    else:
                        result = (None, None, [])
                    
                    self.result_queue.put((result, timestamp))
                else:
                    time.sleep(0.01)  # 短暂休眠避免CPU占用过高
                    
            except Exception as e:
                print(f"Face detection thread error: {e}")
                continue
    
    def stop(self):
        self.running = False


def capture_video_and_mark_faces():
    # 打开默认摄像头
    cap = cv2.VideoCapture(0)

    if not cap.isOpened():
        print("Cannot open camera")
        return

    # 设置摄像头分辨率以提高性能
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, config.PERFORMANCE_CONFIG['camera_width'])
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, config.PERFORMANCE_CONFIG['camera_height'])
    
    # 创建队列用于线程间通信
    frame_queue = Queue(maxsize=config.PERFORMANCE_CONFIG['queue_maxsize'])
    result_queue = Queue(maxsize=config.PERFORMANCE_CONFIG['queue_maxsize'])
    
    # 启动人脸检测线程
    detection_thread = FaceDetectionThread(frame_queue, result_queue)
    detection_thread.start()
    
    # 性能监控变量
    frame_count = 0
    last_fps_time = time.time()
    fps = 0
    current_face_info = None
    current_face_locations = []
    
    print("Press 'q' to quit")
    print("Press 'r' to reset FPS counter")

    try:
        while True:
            # 逐帧捕获
            ret, frame = cap.read()

            if not ret:
                print("Cannot receive frame. Exiting...")
                break

            frame_count += 1
            current_time = time.time()
            
            # 计算FPS
            if current_time - last_fps_time >= 1.0:
                fps = frame_count / (current_time - last_fps_time)
                frame_count = 0
                last_fps_time = current_time
            
            # 将帧发送到检测线程（如果队列未满）
            if not frame_queue.full():
                frame_queue.put((frame.copy(), current_time))
            
            # 获取最新的检测结果
            while not result_queue.empty():
                result, timestamp = result_queue.get()
                # 只使用较新的结果（避免延迟）
                timeout = config.PERFORMANCE_CONFIG['result_timeout']
                if current_time - timestamp < timeout:
                    current_face_info = (result[0], result[1])
                    current_face_locations = result[2]

            # 在图像中标记出人脸
            frame_with_faces = frame.copy()
            
            # 标记检测到的人脸位置
            scale = config.PERFORMANCE_CONFIG['face_detection_scale']
            scale_factor = int(1 / scale)
            for (top, right, bottom, left) in current_face_locations:
                # 将小图像坐标转换为原图像坐标
                top *= scale_factor
                right *= scale_factor
                bottom *= scale_factor
                left *= scale_factor
                cv2.rectangle(frame_with_faces, (left, top), (right, bottom), (0, 255, 0), 2)
            
            # 显示识别结果
            if current_face_info is not None and current_face_info[0] is not None:
                name, distance = current_face_info
                if distance is not None:
                    confidence = 1 - distance
                    if config.DISPLAY_CONFIG['use_chinese']:
                        text = f"用户: {name} (置信度: {confidence:.2f})"
                    else:
                        text = f"User: {name} (Confidence: {confidence:.2f})"
                    threshold = config.PERFORMANCE_CONFIG['confidence_threshold']
                    color = (0, 255, 0) if confidence > threshold else (0, 165, 255)
                else:
                    if config.DISPLAY_CONFIG['use_chinese']:
                        text = f"用户: {name}"
                    else:
                        text = f"User: {name}"
                    color = (0, 255, 255)
                
                # 使用文字绘制函数
                font_size = config.DISPLAY_CONFIG['font_size']
                frame_with_faces = put_chinese_text(frame_with_faces, text, (50, 50), font_size, color)
            else:
                if config.DISPLAY_CONFIG['use_chinese']:
                    text = "未检测到人脸"
                else:
                    text = "No face detected"
                font_size = config.DISPLAY_CONFIG['font_size']
                frame_with_faces = put_chinese_text(frame_with_faces, text, (50, 50), font_size, (0, 0, 255))

            # 显示性能信息
            cv2.putText(frame_with_faces, f"FPS: {fps:.1f}", (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
            cv2.putText(frame_with_faces, f"Queue: {frame_queue.qsize()}/{result_queue.qsize()}", (50, 130), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)

            # 显示结果帧
            window_title = config.DISPLAY_CONFIG['window_title']
            cv2.imshow(window_title, frame_with_faces)

            # 等待按键
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break
            elif key == ord('r'):
                frame_count = 0
                last_fps_time = current_time
                print("FPS counter reset")

    finally:
        # 清理资源
        detection_thread.stop()
        detection_thread.join()
        cap.release()
        cv2.destroyAllWindows()


def main():
    faceUtils.load_known_face_encodings()
    capture_video_and_mark_faces()


if __name__ == "__main__":
    main()
